//
//  DXBluetooh.m
//  BabyBluetoothAppDemo
//
//  Created by 戴义兴 on 2017/4/5.
//

#import "DXBluetooh.h"

#define perophoral @"perophoral"
#define channelOnPeropheralView @"channelOnPeropheral"
#define channelOnCharacter @"channelOnCharacter"
#define channelOnCharacteristicView @"CharacteristicView"

@interface DXBluetooh () {
    NSMutableArray *peripheralDataArray;
    BabyBluetooth *baby;
}

@property (strong, nonatomic)CBPeripheral *currPeripheral;
@property (strong, nonatomic)CBCharacteristic *currReadCharacter;
@property (strong, nonatomic)CBCharacteristic *currWriteCharacter;

@property (assign, nonatomic)BOOL writeBusy;

@end

@implementation DXBluetooh

+ (instancetype)shareBabyBluetooth {
    static DXBluetooh *share = nil;
    static dispatch_once_t oneToken;
    dispatch_once(&oneToken, ^{
        share = [[DXBluetooh alloc] init];
        share.writeBusy = YES;
    });
    return share;
}

- (void)startBluetoothService {
    peripheralDataArray = [NSMutableArray array];
    baby = [BabyBluetooth shareBabyBluetooth];
    [baby cancelAllPeripheralsConnection];
    baby.scanForPeripherals().begin();
//    [self scanDevice];
}

#pragma mark -蓝牙配置和操作

//蓝牙网关初始化和委托方法设置
-(void)scanDeviceWithMacAdress:(NSString *)macAdress
             readCharacterUUID:(NSString *)readCharacterUUID
            writeCharacterUUID:(NSString *)writeCharacterUUID
                  notifiyBlock:(void (^)(NSData * data, NSError *error))notifiyBlock
                     wtiteData:(void (^)(BOOL ready))wtiteDataBlock
               wtiteDataResult:(void (^)(NSData *value, NSError *error))wtiteDataResult
                 readRSSIBlock:(void (^)(NSNumber *RSSI, NSError *error))readRSSIBlock
   failToConnectAtChannelBlock:(void (^)(NSError *error))failToConnectAtChannelBlock
      disconnectAtChannelBlock:(void (^)(NSError *error))disconnectAtChannelBlock {
    
    __weak typeof(self) weakSelf = self;
    __weak typeof(baby) weakBaby = baby;
    [baby setBlockOnCentralManagerDidUpdateState:^(CBCentralManager *central) {
        if (central.state == CBCentralManagerStatePoweredOn) {
            NSLog(@"设备打开成功，开始扫描设备");
//            [SVProgressHUD showInfoWithStatus:@"设备打开成功，开始扫描设备"];
        }
    }];
    
    //设置扫描到设备的委托
    [baby setBlockOnDiscoverToPeripherals:^(CBCentralManager *central, CBPeripheral *peripheral, NSDictionary *advertisementData, NSNumber *RSSI) {
        NSLog(@"搜索到了设备:%@",peripheral.name);
        for (int i=0; i<[advertisementData[@"kCBAdvDataServiceUUIDs"] count]; i++) {
            NSString *peripheralMacAdress = [peripheral.name substringWithRange:NSMakeRange(6, peripheral.name.length - 6)];
            if ([peripheralMacAdress isEqualToString:macAdress]) {
                [weakBaby cancelScan];
                weakSelf.currPeripheral = peripheral;
                [weakSelf connectDeviceWithCharacterUUID:readCharacterUUID
                                      writeCharacterUUID:writeCharacterUUID
                                            notifiyBlock:notifiyBlock
                                               wtiteData:wtiteDataBlock
                                         wtiteDataResult:wtiteDataResult
                                           readRSSIBlock:readRSSIBlock
                             failToConnectAtChannelBlock:failToConnectAtChannelBlock
                                disconnectAtChannelBlock:disconnectAtChannelBlock];
                
                weakBaby.having(weakSelf.currPeripheral).and.channel(channelOnPeropheralView).then.connectToPeripherals().discoverServices().discoverCharacteristics().readValueForCharacteristic().discoverDescriptorsForCharacteristic().readValueForDescriptors().begin();
                
                break;
            }
        }
    }];
    
    
    //设置查找设备的过滤器
    [baby setFilterOnDiscoverPeripherals:^BOOL(NSString *peripheralName, NSDictionary *advertisementData, NSNumber *RSSI) {
        for (int i=0; i<[advertisementData[@"kCBAdvDataServiceUUIDs"] count]; i++) {
            CBUUID *uuid = advertisementData[@"kCBAdvDataServiceUUIDs"][i];
            NSLog(@"$$$$$$$$$$$$%@",uuid.UUIDString);
        }
        if (peripheralName.length >0) {
            return YES;
        }
        return NO;
    }];
    
    [baby setBlockOnCancelAllPeripheralsConnectionBlock:^(CBCentralManager *centralManager) {
        NSLog(@"setBlockOnCancelAllPeripheralsConnectionBlock");
    }];
    
    [baby setBlockOnCancelScanBlock:^(CBCentralManager *centralManager) {
        NSLog(@"setBlockOnCancelScanBlock");
    }];
    
    
    //示例:
    //扫描选项->CBCentralManagerScanOptionAllowDuplicatesKey:忽略同一个Peripheral端的多个发现事件被聚合成一个发现事件
    NSDictionary *scanForPeripheralsWithOptions = @{CBCentralManagerScanOptionAllowDuplicatesKey:@YES};
    //连接设备->
    [baby setBabyOptionsWithScanForPeripheralsWithOptions:scanForPeripheralsWithOptions connectPeripheralWithOptions:nil scanForPeripheralsWithServices:nil discoverWithServices:nil discoverWithCharacteristics:nil];

}



#pragma mark - 连接设备
- (void)connectDeviceWithCharacterUUID:(NSString *)readCharacterUUID
                    writeCharacterUUID:(NSString *)writeCharacterUUID
                          notifiyBlock:(void (^)(NSData * data, NSError *error))notifiyBlock
                             wtiteData:(void (^)(BOOL ready))wtiteDataBlock
                       wtiteDataResult:(void (^)(NSData *value, NSError *error))wtiteDataResult
                        readRSSIBlock:(void (^)(NSNumber *RSSI, NSError *error))readRSSIBlock
           failToConnectAtChannelBlock:(void (^)(NSError *error))failToConnectAtChannelBlock
              disconnectAtChannelBlock:(void (^)(NSError *error))disconnectAtChannelBlock
{
    
    __weak typeof (baby)weakBaby = baby;
    __weak typeof(self)weakSelf = self;
    BabyRhythm *rhythm = [[BabyRhythm alloc]init];
    
    
    //设置设备连接成功的委托,同一个baby对象，使用不同的channel切换委托回调
    [baby setBlockOnConnectedAtChannel:channelOnPeropheralView block:^(CBCentralManager *central, CBPeripheral *peripheral) {
        NSLog(@"设备：%@--连接成功",peripheral.name);
        weakSelf.writeBusy = YES;
//        [SVProgressHUD showInfoWithStatus:[NSString stringWithFormat:@"设备：%@--连接成功",peripheral.name]];
    }];
    
    //设置设备连接失败的委托
    [baby setBlockOnFailToConnectAtChannel:channelOnPeropheralView block:^(CBCentralManager *central, CBPeripheral *peripheral, NSError *error) {
        weakSelf.writeBusy = YES;
        NSLog(@"设备：%@--连接失败",peripheral.name);
//        [SVProgressHUD showInfoWithStatus:[NSString stringWithFormat:@"设备：%@--连接失败",peripheral.name]];
        failToConnectAtChannelBlock(error);
    }];
    
    //设置设备断开连接的委托
    [baby setBlockOnDisconnectAtChannel:channelOnPeropheralView block:^(CBCentralManager *central, CBPeripheral *peripheral, NSError *error) {
        weakSelf.writeBusy = YES;
        NSLog(@"设备：%@--断开连接",peripheral.name);
//        [SVProgressHUD showInfoWithStatus:[NSString stringWithFormat:@"设备：%@--断开失败",peripheral.name]];
        disconnectAtChannelBlock(error);
    }];
    
    //设置发现设备的Services的委托
    [baby setBlockOnDiscoverServicesAtChannel:channelOnPeropheralView block:^(CBPeripheral *peripheral, NSError *error) {
        
//        NSLog(@"%@",peripheral);
//        for (CBService *s in peripheral.services) {
            ///插入section到tableview
//            [weakSelf insertSectionToTableView:s];
//        }
        
        [rhythm beats];
    }];
    //设置发现设service的Characteristics的委托
    [baby setBlockOnDiscoverCharacteristicsAtChannel:channelOnPeropheralView block:^(CBPeripheral *peripheral, CBService *service, NSError *error) {
        NSLog(@"===service name:%@",service.UUID);
        //插入row到tableview
//        [weakSelf insertRowToTableView:service];
        
    }];
    //设置读取characteristics的委托
    [baby setBlockOnReadValueForCharacteristicAtChannel:channelOnPeropheralView block:^(CBPeripheral *peripheral, CBCharacteristic *characteristics, NSError *error) {
        NSLog(@"characteristic name:%@ value is:%@",characteristics.UUID,characteristics.value);
        if ([characteristics.UUID.UUIDString isEqualToString:readCharacterUUID]) { //获取读取数据的特征值
            weakSelf.currReadCharacter = characteristics;
            NSLog(@"********%@",characteristics.UUID.UUIDString);
            weakBaby.channel(channelOnCharacter).characteristicDetails(weakSelf.currPeripheral,weakSelf.currReadCharacter);
            [weakSelf readServiceWithBlock:notifiyBlock];
            [weakSelf setNotifiyWithBlock:notifiyBlock];
        } else if ([characteristics.UUID.UUIDString isEqualToString:writeCharacterUUID]) { //获取写入数据的特征值
            weakSelf.currWriteCharacter = characteristics;
            weakBaby.channel(channelOnCharacteristicView).characteristicDetails(weakSelf.currPeripheral,weakSelf.currWriteCharacter);
            weakSelf.writeBusy = NO;
            wtiteDataBlock(YES);
        }
    }];
    //设置发现characteristics的descriptors的委托
    [baby setBlockOnDiscoverDescriptorsForCharacteristicAtChannel:channelOnPeropheralView block:^(CBPeripheral *peripheral, CBCharacteristic *characteristic, NSError *error) {
        NSLog(@"===characteristic name:%@",characteristic.service.UUID);
        for (CBDescriptor *d in characteristic.descriptors) {
            NSLog(@"CBDescriptor name is :%@",d.UUID);
        }
    }];
    //设置读取Descriptor的委托
    [baby setBlockOnReadValueForDescriptorsAtChannel:channelOnPeropheralView block:^(CBPeripheral *peripheral, CBDescriptor *descriptor, NSError *error) {
        NSLog(@"Descriptor name:%@ value is:%@",descriptor.characteristic.UUID, descriptor.value);
    }];
    
    //读取rssi的委托
    [baby setBlockOnDidReadRSSI:^(NSNumber *RSSI, NSError *error) {
        NSLog(@"setBlockOnDidReadRSSI:RSSI:%@",RSSI);
        readRSSIBlock(RSSI, error);
    }];
    
    //设置写数据成功的block
    [baby setBlockOnDidWriteValueForCharacteristicAtChannel:channelOnCharacteristicView block:^(CBCharacteristic *characteristic, NSError *error) {
        NSLog(@"setBlockOnDidWriteValueForCharacteristicAtChannel characteristic:%@ and new value:%@",characteristic.UUID, characteristic.value);
        wtiteDataResult(characteristic.value, error);
    }];
    
    //设置beats break委托
    [rhythm setBlockOnBeatsBreak:^(BabyRhythm *bry) {
        NSLog(@"setBlockOnBeatsBreak call");
        
        //如果完成任务，即可停止beat,返回bry可以省去使用weak rhythm的麻烦
        //        if (<#condition#>) {
        //            [bry beatsOver];
        //        }
        
    }];
    
    //设置beats over委托
    [rhythm setBlockOnBeatsOver:^(BabyRhythm *bry) {
        NSLog(@"setBlockOnBeatsOver call");
    }];
    
    //扫描选项->CBCentralManagerScanOptionAllowDuplicatesKey:忽略同一个Peripheral端的多个发现事件被聚合成一个发现事件
    NSDictionary *scanForPeripheralsWithOptions = @{CBCentralManagerScanOptionAllowDuplicatesKey:@YES};
    /*连接选项->
     CBConnectPeripheralOptionNotifyOnConnectionKey :当应用挂起时，如果有一个连接成功时，如果我们想要系统为指定的peripheral显示一个提示时，就使用这个key值。
     CBConnectPeripheralOptionNotifyOnDisconnectionKey :当应用挂起时，如果连接断开时，如果我们想要系统为指定的peripheral显示一个断开连接的提示时，就使用这个key值。
     CBConnectPeripheralOptionNotifyOnNotificationKey:
     当应用挂起时，使用该key值表示只要接收到给定peripheral端的通知就显示一个提
     */
    NSDictionary *connectOptions = @{CBConnectPeripheralOptionNotifyOnConnectionKey:@YES,
                                     CBConnectPeripheralOptionNotifyOnDisconnectionKey:@YES,
                                     CBConnectPeripheralOptionNotifyOnNotificationKey:@YES};
    
    [baby setBabyOptionsAtChannel:channelOnPeropheralView scanForPeripheralsWithOptions:scanForPeripheralsWithOptions connectPeripheralWithOptions:connectOptions scanForPeripheralsWithServices:nil discoverWithServices:nil discoverWithCharacteristics:nil];
}


#pragma mark - 读取服务

- (void)readServiceWithBlock:(void (^)(NSData * data, NSError *error))block {
    __weak typeof(self)weakSelf = self;
    //设置读取characteristics的委托
    [baby setBlockOnReadValueForCharacteristicAtChannel:channelOnCharacter block:^(CBPeripheral *peripheral, CBCharacteristic *characteristics, NSError *error) {
        NSLog(@"CharacteristicViewController===characteristic name:%@ value is:%@",characteristics.UUID,characteristics.value);
    }];
    //设置发现characteristics的descriptors的委托
    [baby setBlockOnDiscoverDescriptorsForCharacteristicAtChannel:channelOnCharacter block:^(CBPeripheral *peripheral, CBCharacteristic *characteristic, NSError *error) {
        //        NSLog(@"CharacteristicViewController===characteristic name:%@",characteristic.service.UUID);
        for (CBDescriptor *d in characteristic.descriptors) {
            NSLog(@"CharacteristicViewController CBDescriptor name is :%@",d.UUID);
        }
    }];
    //设置读取Descriptor的委托
    [baby setBlockOnReadValueForDescriptorsAtChannel:channelOnCharacter block:^(CBPeripheral *peripheral, CBDescriptor *descriptor, NSError *error) {
        NSLog(@"CharacteristicViewController Descriptor name:%@ value is:%@",descriptor.characteristic.UUID, descriptor.value);
    }];
    
    //设置写数据成功的block
    [baby setBlockOnDidWriteValueForCharacteristicAtChannel:channelOnCharacter block:^(CBCharacteristic *characteristic, NSError *error) {
        NSLog(@"setBlockOnDidWriteValueForCharacteristicAtChannel characteristic:%@ and new value:%@",characteristic.UUID, characteristic.value);
    }];
    
    //设置通知状态改变的block
    [baby setBlockOnDidUpdateNotificationStateForCharacteristicAtChannel:channelOnCharacter block:^(CBCharacteristic *characteristic, NSError *error) {
        NSLog(@"uid:%@,isNotifying:%@",characteristic.UUID,characteristic.isNotifying?@"on":@"off");
    }];
}


//接受通知
-(void)setNotifiyWithBlock:(void (^)(NSData * data, NSError *error))block{
    
    __weak typeof(self)weakSelf = self;
    if(self.currPeripheral.state != CBPeripheralStateConnected) {
//        [SVProgressHUD showErrorWithStatus:@"peripheral已经断开连接，请重新连接"];
        return;
    }
    if (self.currReadCharacter.properties & CBCharacteristicPropertyNotify ||  self.currReadCharacter.properties & CBCharacteristicPropertyIndicate) {
        
        if(self.currReadCharacter.isNotifying) {
            [baby cancelNotify:self.currPeripheral characteristic:self.currReadCharacter];
        }else{
            [weakSelf.currPeripheral setNotifyValue:YES forCharacteristic:self.currReadCharacter];
            [baby notify:self.currPeripheral
          characteristic:self.currReadCharacter
                   block:^(CBPeripheral *peripheral, CBCharacteristic *characteristics, NSError *error) {
                       
                       NSLog(@"notify block");
                       NSLog(@"new value %@",characteristics.value);
                       block(characteristics.value,error);
                   }];
        }
    }
    else{
//        [SVProgressHUD showErrorWithStatus:@"这个characteristic没有nofity的权限"];
        return;
    }
    
}

//写入值
- (void)writeValueWith:(Byte *)byte lenght:(NSInteger)lenght {
    NSData *data = [NSData dataWithBytes:byte length:lenght];
    [self.currPeripheral writeValue:data forCharacteristic:self.currWriteCharacter type:CBCharacteristicWriteWithResponse];
}

// 同步时间应答
- (void)respondTimeToHardware {
    NSDate *dateNow = [[NSDate alloc] init];
    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];//设置成中国阳历
    NSDateComponents *comps = [[NSDateComponents alloc] init];
    NSInteger unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | kCFCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
    comps = [calendar components:unitFlags fromDate:dateNow];
    
    long year=[comps year];
    long year1 = year / 100;
    long year2 = year % 100;
    long month=[comps month];
    long day=[comps day];
    long hour=[comps hour];
    long minute=[comps minute];
    long second=[comps second];
    
    
    Byte time[] = {0xF1, 0x0A, 0xD1, year1, year2, month, day, hour, minute, second};
    [self writeValueWith:time lenght:sizeof(time)];
    
}

// 连接状态下同步计步数据应答
- (void)respondsynStep {
    Byte cancelActivation[] = {0xF1, 0x03, 0xD2};
    [self writeValueWith:cancelActivation lenght:sizeof(cancelActivation)];
}

// 连接状态下同步坐姿数据应答
- (void)respondsynPosture {
    Byte posture[] = {0xF1, 0x03, 0xD3};
    [self writeValueWith:posture lenght:sizeof(posture)];
}

// 交换结束应答
- (void)respondComplete {
    Byte complete[] = {0xF1, 0x03, 0xD4};
    [self writeValueWith:complete lenght:sizeof(complete)];
}

// 获取电池电量
- (void)getBattary {
    Byte battary[] = {0xF1, 0x03, 0xD5};
    [self writeValueWith:battary lenght:sizeof(battary)];
}

// 激活命令
- (void)activation {
    Byte activation[] = {0xF1, 0x03, 0xD6, 0xB2};
    [self writeValueWith:activation lenght:sizeof(activation)];
}


// 取消激活命令
- (void)cancelActivation {
    Byte cancelActivation[] = {0xF1, 0x03, 0xD7, 0xB3};
    [self writeValueWith:cancelActivation lenght:sizeof(cancelActivation)];
}

// 连接状态下同步计步数据
- (void)synStep {
    Byte cancelActivation[] = {0xF1, 0x03, 0xD8};
    [self writeValueWith:cancelActivation lenght:sizeof(cancelActivation)];
}

// 连接状态下同步坐姿数据
- (void)synPosture {
    Byte posture[] = {0xF1, 0x03, 0xD9};
    [self writeValueWith:posture lenght:sizeof(posture)];
}

// 设置马达震动
- (void)setMotor:(BOOL)open shockTime:(NSInteger)shockTime{
    if (!open) {
        Byte motor[] = {0xF1, 0x04, 0xDA, 0xF0};
        [self writeValueWith:motor lenght:sizeof(motor)];
        return;
    }
    
    Byte motor[] = {0xF1, 0x05, 0xDA, 0xF5, shockTime};
    [self writeValueWith:motor lenght:sizeof(motor)];
}

// 读取马达震动
- (void)getMotor {
    Byte motor[] = {0xF1, 0x03, 0xDC};
    [self writeValueWith:motor lenght:sizeof(motor)];
}

// 设置校准坐姿
- (void)setPosture {
    Byte pos[] = {0xF1, 0x03, 0xDC};
    [self writeValueWith:pos lenght:sizeof(pos)];
}

// 重启
- (void)restart {
    Byte restart[] = {0xF1, 0x03, 0xDD};
    [self writeValueWith:restart lenght:sizeof(restart)];
}


@end
